Перейти к основному содержимому

Указатели и массивы как параметры функции

Массивы как параметры функций

При передаче массива в функцию передается указатель на его первый элемент, а не копия всего массива.

void processArray(int arr[], int size) {
// arr — это указатель на первый элемент массива
}

Способы объявления массивов в параметрах

Эквивалентные формы записи

#include <stdio.h>

// Все эти объявления эквивалентны:
void method1(int arr[], int size) {
printf("Форма 1: arr[] - %d элементов\n", size);
}

void method2(int arr[10], int size) { // Размер игнорируется!
printf("Форма 2: arr[10] - %d элементов\n", size);
}

void method3(int *arr, int size) {
printf("Форма 3: *arr - %d элементов\n", size);
}

int main() {
int data[5] = {1, 2, 3, 4, 5};

method1(data, 5);
method2(data, 5); // Размер 10 в объявлении не важен
method3(data, 5);

return 0;
}

Передача указателей как параметров

Изменение переменных через указатели

#include <stdio.h>

void swapValues(int *a, int *b) {
int temp = *a;
*a = *b;
*b = temp;
}

void updateBalance(float *balance, float amount, char operation) {
printf("Текущий баланс: %.2f\n", *balance);

if (operation == '+') {
*balance += amount;
printf("Пополнение на %.2f\n", amount);
} else if (operation == '-') {
if (*balance >= amount) {
*balance -= amount;
printf("Списание %.2f\n", amount);
} else {
printf("Недостаточно средств\n");
}
}

printf("Новый баланс: %.2f\n", *balance);
}

int main() {
int x = 10, y = 20;
printf("До обмена: x = %d, y = %d\n", x, y);

swapValues(&x, &y); // Передаем адреса переменных

printf("После обмена: x = %d, y = %d\n", x, y);

float account = 500.0;
printf("\n=== БАНКОВСКИЕ ОПЕРАЦИИ ===\n");
updateBalance(&account, 150.0, '+');
updateBalance(&account, 200.0, '-');
updateBalance(&account, 1000.0, '-');

return 0;
}

Обработка массивов в функциях

Поиск и анализ

#include <stdio.h>

int findElement(int arr[], int size, int target) {
for (int i = 0; i < size; i++) {
if (arr[i] == target) {
return i; // Возвращаем индекс найденного элемента
}
}
return -1; // Элемент не найден
}

int* findElementPtr(int arr[], int size, int target) {
for (int i = 0; i < size; i++) {
if (arr[i] == target) {
return &arr[i]; // Возвращаем указатель на элемент
}
}
return NULL; // Элемент не найден
}

int main() {
int data[8] = {15, 42, 8, 73, 29, 56, 91, 34};
int searchValue = 73;

// Поиск по индексу
int index = findElement(data, 8, searchValue);
if (index >= 0) {
printf("Элемент %d найден на позиции %d\n", searchValue, index);
}

// Поиск по указателю
int *foundPtr = findElementPtr(data, 8, searchValue);
if (foundPtr != NULL) {
printf("Найденный элемент: %d\n", *foundPtr);
*foundPtr = 999; // Можем изменить через указатель
printf("Изменили на: %d\n", data[index]);
}

return 0;
}

Модификация массивов через функции

Прямое изменение элементов

#include <stdio.h>

void fillArray(int arr[], int size, int value) {
for (int i = 0; i < size; i++) {
arr[i] = value;
}
}

void multiplyArray(int arr[], int size, int multiplier) {
for (int i = 0; i < size; i++) {
arr[i] *= multiplier;
}
}

void reverseArray(int arr[], int size) {
for (int i = 0; i < size / 2; i++) {
int temp = arr[i];
arr[i] = arr[size - 1 - i];
arr[size - 1 - i] = temp;
}
}

int main() {
int numbers[6];

// Заполняем массив
fillArray(numbers, 6, 5);
printf("После заполнения: ");
for (int i = 0; i < 6; i++) printf("%d ", numbers[i]);
printf("\n");

// Умножаем на 3
multiplyArray(numbers, 6, 3);
printf("После умножения на 3: ");
for (int i = 0; i < 6; i++) printf("%d ", numbers[i]);
printf("\n");

// Переворачиваем
reverseArray(numbers, 6);
printf("После переворота: ");
for (int i = 0; i < 6; i++) printf("%d ", numbers[i]);
printf("\n");

return 0;
}

Работа со строками как параметрами

Функции обработки строк

#include <stdio.h>

int stringLength(char *str) {
int length = 0;
while (str[length] != '\0') {
length++;
}
return length;
}

void analyzeString(char str[], int *length, int *vowels, int *consonants) {
*length = 0;
*vowels = 0;
*consonants = 0;

while (str[*length] != '\0') {
char ch = str[*length];

if ((ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z')) {
if (ch == 'a' || ch == 'e' || ch == 'i' || ch == 'o' || ch == 'u' ||
ch == 'A' || ch == 'E' || ch == 'I' || ch == 'O' || ch == 'U') {
(*vowels)++;
} else {
(*consonants)++;
}
}

(*length)++;
}
}

int main() {
char text[] = "Programming in C language";
int len, vowelCount, consonantCount;

analyzeString(text, &len, &vowelCount, &consonantCount);

printf("Текст: \"%s\"\n", text);
printf("Длина: %d символов\n", len);
printf("Гласных: %d\n", vowelCount);
printf("Согласных: %d\n", consonantCount);

return 0;
}

Многомерные массивы как параметры

Двумерные массивы

#include <stdio.h>

void printMatrix(int matrix[][4], int rows) { // Количество столбцов обязательно!
printf("Матрица %d×4:\n", rows);

for (int i = 0; i < rows; i++) {
for (int j = 0; j < 4; j++) {
printf("%3d ", matrix[i][j]);
}
printf("\n");
}
}

int calculateMatrixSum(int matrix[][4], int rows) {
int sum = 0;

for (int i = 0; i < rows; i++) {
for (int j = 0; j < 4; j++) {
sum += matrix[i][j];
}
}

return sum;
}

void fillMatrix(int matrix[][4], int rows, int value) {
for (int i = 0; i < rows; i++) {
for (int j = 0; j < 4; j++) {
matrix[i][j] = value + i + j;
}
}
}

int main() {
int data[3][4];

fillMatrix(data, 3, 10);
printMatrix(data, 3);

int sum = calculateMatrixSum(data, 3);
printf("Сумма элементов: %d\n", sum);

return 0;
}

Функции возвращающие указатели

Возврат указателей на элементы массива

#include <stdio.h>

int* findMax(int arr[], int size) {
if (size <= 0) return NULL;

int *maxPtr = &arr[0]; // Указатель на первый элемент

for (int i = 1; i < size; i++) {
if (arr[i] > *maxPtr) {
maxPtr = &arr[i]; // Запоминаем адрес нового максимума
}
}

return maxPtr;
}

int* findMin(int arr[], int size) {
if (size <= 0) return NULL;

int *minPtr = arr; // Указатель на первый элемент

for (int i = 1; i < size; i++) {
if (*(arr + i) < *minPtr) {
minPtr = arr + i; // Адрес нового минимума
}
}

return minPtr;
}

int main() {
int values[8] = {45, 12, 78, 34, 89, 23, 67, 56};

int *maxElement = findMax(values, 8);
int *minElement = findMin(values, 8);

if (maxElement != NULL) {
printf("Максимальный элемент: %d\n", *maxElement);
printf("Его позиция: %ld\n", maxElement - values);

*maxElement = 999; // Изменяем через указатель
printf("Изменили максимум на: %d\n", *maxElement);
}

if (minElement != NULL) {
printf("Минимальный элемент: %d\n", *minElement);
printf("Его позиция: %ld\n", minElement - values);
}

return 0;
}

Константные параметры

Защита данных от изменений

#include <stdio.h>

void printArrayReadOnly(const int arr[], int size) {
printf("Массив (только чтение): ");
for (int i = 0; i < size; i++) {
printf("%d ", arr[i]);
// arr[i] = 0; // Ошибка компиляции! Константный массив
}
printf("\n");
}

int calculateSum(const int *arr, int size) {
int sum = 0;
for (int i = 0; i < size; i++) {
sum += arr[i]; // Можем читать
// arr[i] *= 2; // Ошибка! Нельзя изменять
}
return sum;
}

void processString(const char *input, char *output) {
int i = 0;
while (input[i] != '\0') {
output[i] = input[i]; // Копируем из константной строки
i++;
}
output[i] = '\0';

// input[0] = 'X'; // Ошибка! input защищена от изменений
}

int main() {
int data[5] = {10, 20, 30, 40, 50};
char source[] = "Исходный текст";
char destination[50];

printArrayReadOnly(data, 5); // Безопасный вывод

int sum = calculateSum(data, 5);
printf("Сумма элементов: %d\n", sum);

processString(source, destination);
printf("Скопированная строка: \"%s\"\n", destination);

return 0;
}

Практические применения

Библиотека обработки массивов

#include <stdio.h>

// Сортировка массива
void bubbleSort(int arr[], int size) {
for (int i = 0; i < size - 1; i++) {
for (int j = 0; j < size - 1 - i; j++) {
if (arr[j] > arr[j + 1]) {
// Обмен элементов
int temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
}

// Фильтрация элементов
int filterArray(int source[], int sourceSize, int target[], int minValue) {
int targetIndex = 0;

for (int i = 0; i < sourceSize; i++) {
if (source[i] >= minValue) {
target[targetIndex] = source[i];
targetIndex++;
}
}

return targetIndex; // Количество отфильтрованных элементов
}

// Объединение массивов
void mergeArrays(int arr1[], int size1, int arr2[], int size2, int result[]) {
int i = 0;

// Копируем первый массив
for (int j = 0; j < size1; j++) {
result[i++] = arr1[j];
}

// Копируем второй массив
for (int j = 0; j < size2; j++) {
result[i++] = arr2[j];
}
}

int main() {
int original[8] = {64, 34, 25, 12, 22, 11, 90, 5};
int filtered[8];
int sorted[8];
int combined[16];
int additional[4] = {100, 200, 300, 400};

printf("Исходный массив: ");
for (int i = 0; i < 8; i++) printf("%d ", original[i]);
printf("\n");

// Фильтруем элементы >= 20
int filteredCount = filterArray(original, 8, filtered, 20);
printf("Отфильтровано (%d элементов): ", filteredCount);
for (int i = 0; i < filteredCount; i++) printf("%d ", filtered[i]);
printf("\n");

// Копируем для сортировки
for (int i = 0; i < 8; i++) sorted[i] = original[i];

bubbleSort(sorted, 8);
printf("Отсортированный: ");
for (int i = 0; i < 8; i++) printf("%d ", sorted[i]);
printf("\n");

// Объединяем массивы
mergeArrays(original, 8, additional, 4, combined);
printf("Объединенный: ");
for (int i = 0; i < 12; i++) printf("%d ", combined[i]);
printf("\n");

return 0;
}
Ключевые принципы
  • Массивы передаются по ссылке — изменения влияют на исходный массив
  • Всегда передавайте размер массива отдельным параметром
  • Используйте const для параметров, которые не должны изменяться
  • Функции могут возвращать указатели на элементы переданных массивов
Лучшие практики
  • Проверяйте параметры на корректность (NULL, размер > 0)
  • Используйте осмысленные имена параметров
  • Документируйте ожидаемый размер массива
  • Защищайте данные через const при необходимости
Частые ошибки
  • Забывать передавать размер массива
  • Пытаться получить размер массива через sizeof() в функции
  • Изменять массивы, когда нужно только читать
  • Возвращать указатели на локальные переменные

Передача указателей и массивов в функции — основа для создания эффективных и переиспользуемых программных модулей.